package handler;

import java.io.*;
import java.util.zip.*;

/**
 * Handles the compression and decompression of streams. This class is
 * essentially a utility class that is used elsewhere in the program to support
 * compressed Notebook files. None of the methods in this class will close the
 * InputStream/OutputStream they are provided with. It is the responsibility of
 * the caller to close these provided streams.
 * 
 * @author Jared Schlicht
 */
public class CompressionHandler {
    /**
     * Specifies the size of a buffer that will be used for GZIP operations.
     */
	private static final int BUFFER_SIZE = 512;
	
	/**
	 * Reads data from the input stream, compresses it, and sends the compressed
	 * data to the output stream. The caller is responsible for closing the
	 * provided InputStream and OutputStream.
	 * 
	 * @author Jared Schlicht
	 * @param input stream to read data from
	 * @param output stream to send compressed data to
	 * @return true if the compression occurred without errors, false otherwise.
	 */
	public boolean compress(InputStream input, OutputStream output) {
		byte[] buffer = new byte[BUFFER_SIZE];
		
		try {
			GZIPOutputStream zipOut = new GZIPOutputStream(output, BUFFER_SIZE);
			int length;
			while ((length = input.read(buffer, 0, BUFFER_SIZE)) != -1) {
				zipOut.write(buffer, 0, length);
			}
			zipOut.finish();
			zipOut.flush();
			return true;
		} catch (IOException e) {
			return false;
		}
	}
	
	/**
	 * Reads compressed data from the input stream, decompresses it, and sends
	 * the decompressed data to the output stream. The caller is responsible for
	 * closing the provided InputStream and OutputStream.
	 * 
	 * @author Jared Schlicht
	 * @param input stream to read compressed data from
	 * @param output stream to send decompressed data to
	 * @return true if the decompression occurred without errors, false otherwise.
	 */
	public boolean decompress(InputStream input, OutputStream output) {
		byte[] buffer = new byte[BUFFER_SIZE];
		
		try {
			GZIPInputStream zipIn = new GZIPInputStream(input, BUFFER_SIZE);
			int length;
			while ((length = zipIn.read(buffer, 0, BUFFER_SIZE)) != -1) {
				output.write(buffer, 0, length);
			}
			output.flush();
			return true;
		} catch (IOException e) {
			return false;
		}
	}	
}
